﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace AnChao.WPF.Controls.CheckBoxList.Controls
{
    [TemplatePart(Name = PART_CheckBoxList, Type = typeof(ToggleButton))]
    [TemplatePart(Name = PART_ContentPresenter, Type = typeof(ContentPresenter))]
    [TemplatePart(Name = PART_TextBox, Type = typeof(TextBox))]
    [TemplatePart(Name = PART_Popup, Type = typeof(Popup))]
    public class CheckBoxList : ContentControl, ICommandSource
    {
        private const string PART_CheckBoxList = "PART_CheckBoxList";
        private const string PART_ContentPresenter = "PART_ContentPresenter";
        private const string PART_ToggleButton = "PART_ToggleButton";
        private const string PART_Popup = "PART_Popup";
        private const string PART_TextBox = "PART_TextBox";

        #region Members

        private ContentPresenter _contentPresenter;
        private Popup _popup;
        private ItemsControl _container;
        private TextBox _textBox;

        #endregion

        static CheckBoxList()
        {
            //DefaultStyleKeyProperty.OverrideMetadata(typeof(CheckBoxList), new FrameworkPropertyMetadata(typeof(CheckBoxList)));
        }

        public CheckBoxList()
        {
            this.Loaded += CheckBoxList_Loaded; ;
        }

        #region 属性

        private System.Windows.Controls.Primitives.ButtonBase _button;
        protected System.Windows.Controls.Primitives.ButtonBase Button
        {
            get
            {
                return _button;
            }
            set
            {
                if (_button != null)
                    _button.Click -= CheckBoxList_Click;

                _button = value;

                if (_button != null)
                    _button.Click += CheckBoxList_Click;
            }
        }


        #region IsOpen

        public static readonly DependencyProperty IsOpenProperty =
            DependencyProperty.Register("IsOpen",
            typeof(bool),
            typeof(CheckBoxList),
            new UIPropertyMetadata(false, OnIsOpenChanged));
        /// <summary>
        /// DropDownContent是否打开
        /// </summary>
        public bool IsOpen
        {
            get
            {
                return (bool)GetValue(IsOpenProperty);
            }
            set
            {
                SetValue(IsOpenProperty, value);
            }
        }

        private static void OnIsOpenChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            CheckBoxList CheckBoxList = o as CheckBoxList;
            if (CheckBoxList != null)
                CheckBoxList.OnIsOpenChanged((bool)e.OldValue, (bool)e.NewValue);
        }

        protected virtual void OnIsOpenChanged(bool oldValue, bool newValue)
        {
            if (newValue)
                RaiseRoutedEvent(CheckBoxList.OpenedEvent);
            else
                RaiseRoutedEvent(CheckBoxList.ClosedEvent);
        }




        #endregion

        #region 数据源

        /// <summary>
        /// 数据源
        /// </summary>
        public IList ItemsSource
        {
            get { return (IList)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }

        public static readonly DependencyProperty ItemsSourceProperty =
           DependencyProperty.Register("ItemsSource",
           typeof(IList),
           typeof(CheckBoxList),
           new UIPropertyMetadata(null));

        #endregion

        #region DisplayMemberPath


        public string DisplayMemberPath
        {
            get { return (string)GetValue(DisplayMemberPathProperty); }
            set { SetValue(DisplayMemberPathProperty, value); }
        }

        // Using a DependencyProperty as the backing store for DisplayMemberPath.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DisplayMemberPathProperty =
            DependencyProperty.Register("DisplayMemberPath", typeof(string), typeof(CheckBoxList), new PropertyMetadata(string.Empty));


        #endregion

        #region SelectedItems
        /// <summary>
        /// 选中的项，支持多选
        /// </summary>
        public IList SelectedItems
        {
            get { return (IList)GetValue(SelectedItemsProperty); }
            set { SetValue(SelectedItemsProperty, value); }
        }

        public static readonly DependencyProperty SelectedItemsProperty =
            DependencyProperty.Register("SelectedItems",
            typeof(IList),
            typeof(CheckBoxList),
            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.Journal, SelectedItemsChanged));

        static void SelectedItemsChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            CheckBoxList combo = obj as CheckBoxList;
            if (e.NewValue == null)
                return;

            var selectedItems = e.NewValue as IList;
            if (selectedItems == null)
                return;

            string dot = ".";

            var selectedTextPath = obj.GetValue(CheckBoxList.SelectedTextPathProperty) as string;
            if (selectedTextPath == null || selectedTextPath.Equals(dot))
                return;

            List<string> displayContents = new List<string>();
            foreach (var item in selectedItems)
            {
                var propArray = selectedTextPath.Split('.').ToList();
                var displayContent = GetBindingValue(propArray, item);
                if (!string.IsNullOrEmpty(displayContent))
                    displayContents.Add(displayContent);
            }

            var displayText = string.Empty;
            if (displayContents.Count > 0)
            {
                displayText = string.Join(",", displayContents.ToArray());
            }
            obj.SetValue(CheckBoxList.DisplayTextProperty, displayText);

            if (combo.IsLoaded && combo._container != null && combo.IsVisible)
            {
                foreach (var checkbox in combo.GetCheckBoxes())
                {
                    if (checkbox == null)
                        continue;

                    if (selectedItems.Contains(checkbox.DataContext))
                    {
                        checkbox.IsChecked = true;
                    }
                    else
                    {
                        checkbox.IsChecked = false;
                    }
                }
            }
        }

        private static string GetBindingValue(List<string> propArray, object source)
        {
            if (source == null)
                return string.Empty;

            while (propArray.Count > 0)
            {
                var first = propArray[0];
                propArray.RemoveAt(0);
                var propertyValue = GetPropertyValue(source, first);
                if (propertyValue == null)
                    return string.Empty;
                if (propArray.Count == 0)
                    return propertyValue.ToString();
                else
                {
                    source = propertyValue;
                }
            }
            return string.Empty;
        }

        private static object GetPropertyValue(object target, string path)
        {
            var property = target.GetType().GetProperties().FirstOrDefault(x => x.Name.Equals(path));
            if (property != null)
                return property.GetValue(target, null);
            return null;
        }

        #endregion

        #region DisplayText

        /// <summary>
        /// ComboBox列出选中的项，多选以"，"连接
        /// </summary>
        public string DisplayText
        {
            get { return (string)GetValue(DisplayTextProperty); }
            set { SetValue(DisplayTextProperty, value); }
        }

        public static readonly DependencyProperty DisplayTextProperty =
            DependencyProperty.Register("DisplayText",
            typeof(string),
            typeof(CheckBoxList),
            new UIPropertyMetadata(null));

        #endregion

        #region DefaultText

        /// <summary>
        /// 下拉框默认显示的文字
        /// </summary>
        public string DefaultText
        {
            get { return (string)GetValue(DefaultTextProperty); }
            set { SetValue(DefaultTextProperty, value); }
        }

        public static readonly DependencyProperty DefaultTextProperty =
            DependencyProperty.Register("DefaultText",
            typeof(string),
            typeof(CheckBoxList),
            new UIPropertyMetadata(null));
        #endregion

        #region SelectedTextPath

        /// <summary>
        /// 绑定文本框的路径
        /// </summary>
        public string SelectedTextPath
        {
            get { return (string)GetValue(SelectedTextPathProperty); }
            set { SetValue(SelectedTextPathProperty, value); }
        }
        public static readonly DependencyProperty SelectedTextPathProperty =
            DependencyProperty.Register("SelectedTextPath",
            typeof(string),
            typeof(CheckBoxList),
            new UIPropertyMetadata("."));

        #endregion

        #region DisableItems不可更改状态的项

        public static readonly DependencyProperty DisableItemsProperty = DependencyProperty.Register(
            "DisableItems", typeof(IList), typeof(CheckBoxList), new PropertyMetadata(default(IList)));

        public IList DisableItems
        {
            get { return (IList)GetValue(DisableItemsProperty); }
            set { SetValue(DisableItemsProperty, value); }
        }
        #endregion

        #region DropDownBackground

        /// <summary>
        /// 下拉框背景色
        /// </summary>
        public Brush DropDownBackground
        {
            get { return (Brush)GetValue(DropDownBackgroundProperty); }
            set { SetValue(DropDownBackgroundProperty, value); }
        }

        public static readonly DependencyProperty DropDownBackgroundProperty =
            DependencyProperty.Register("DropDownBackground",
            typeof(Brush),
            typeof(CheckBoxList),
            new UIPropertyMetadata(null));

        #endregion

        #region DropDownForeground


        public Brush DropDownForeground
        {
            get { return (Brush)GetValue(DropDownForegroundProperty); }
            set { SetValue(DropDownForegroundProperty, value); }
        }

        public static readonly DependencyProperty DropDownForegroundProperty =
            DependencyProperty.Register("DropDownForeground",
            typeof(Brush),
            typeof(CheckBoxList),
            new UIPropertyMetadata(null));


        #endregion

        #region ShowCheckAll

        public static readonly DependencyProperty ShowCheckAllProperty =
            DependencyProperty.Register("ShowCheckAll",
            typeof(bool),
            typeof(CheckBoxList),
            new UIPropertyMetadata(false));
        /// <summary>
        /// DropDownContent是否打开
        /// </summary>
        public bool ShowCheckAll
        {
            get
            {
                return (bool)GetValue(ShowCheckAllProperty);
            }
            set
            {
                SetValue(ShowCheckAllProperty, value);
            }
        }
        #endregion

        #region IsCheckAll

        public static readonly DependencyProperty IsCheckAllProperty =
            DependencyProperty.Register("IsCheckAll",
            typeof(bool),
            typeof(CheckBoxList),
            new UIPropertyMetadata(false, OnIsCheckAllChanged));
        /// <summary>
        /// IsCheckAll
        /// </summary>
        public bool IsCheckAll
        {
            get
            {
                return (bool)GetValue(IsCheckAllProperty);
            }
            set
            {
                SetValue(IsCheckAllProperty, value);
            }
        }

        private static void OnIsCheckAllChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            CheckBoxList CheckBoxList = o as CheckBoxList;
            if (CheckBoxList != null)
                CheckBoxList.OnIsCheckAllChanged((bool)e.OldValue, (bool)e.NewValue);
        }

        protected virtual void OnIsCheckAllChanged(bool oldValue, bool newValue)
        {
            if (innerChangedAll == true || SelectedItems == null)
                return;

            if (newValue)
            {
                SelectedItems.Clear();//先清除，不然SelectedItems里顺序不好控制
                foreach (var checkbox in GetCheckBoxes())
                {
                    if (checkbox == null)
                        continue;
                    if (DisableItems != null && DisableItems.Contains(checkbox.DataContext))
                    {
                        checkbox.IsEnabled = false;
                        continue;
                    }

                    checkbox.IsChecked = true;
                    SelectedItems.Add(checkbox.DataContext);
                }
            }
            else
            {
                foreach (var checkbox in GetCheckBoxes())
                {
                    if (checkbox == null)
                        continue;
                    if (DisableItems != null && DisableItems.Contains(checkbox.DataContext))
                    {
                        checkbox.IsEnabled = false;
                        continue;
                    }

                    checkbox.IsChecked = false;
                    SelectedItems.Remove(checkbox.DataContext);
                }
            }

            innerChangedAll = true;
            RefreshDisplayText();
            innerChangedAll = false;
        }
        #endregion


        #endregion

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            Button = GetTemplateChild(PART_CheckBoxList) as ToggleButton;


            if (_contentPresenter != null)
            {
                _contentPresenter.PreviewKeyDown -= _popup_KeyDown;
            }
            _contentPresenter = GetTemplateChild(PART_ContentPresenter) as ContentPresenter;
            if (_contentPresenter != null)
            {
                _contentPresenter.PreviewKeyDown += _popup_KeyDown;
            }

            if (_textBox != null)
            {
                _textBox.PreviewKeyDown -= _popup_KeyDown;
            }
            _textBox = GetTemplateChild(PART_TextBox) as TextBox;
            if (_textBox != null)
            {
                _textBox.PreviewKeyDown += _popup_KeyDown;
            }

            if (_popup != null)
            {
                _popup.Opened -= Popup_Opened;
                _popup.PreviewKeyDown -= _popup_KeyDown;
            }
            _popup = GetTemplateChild(PART_Popup) as Popup;
            if (_popup != null)
            {
                _popup.Opened += Popup_Opened;
                _popup.PreviewKeyDown += _popup_KeyDown;
            }

            AddHandler(Mouse.PreviewMouseDownOutsideCapturedElementEvent, new MouseButtonEventHandler(OnMouseDownOutsideCapturedElement));
            _container = GetTemplateChild("checkBoxContainer") as ItemsControl;
            RefreshCheckboxState();
            //_popup.Opened += _popup_Opened;
            this.IsVisibleChanged += CheckBoxList_IsVisibleChanged;
        }

        private void CheckBoxList_Loaded(object sender, RoutedEventArgs e)
        {
            RefreshDisplay();
        }

        private void CheckBoxList_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            try
            {
                if (e.NewValue != null && (bool)e.NewValue)
                {
                    RefreshCheckboxState();
                }

                if (this.Visibility == Visibility.Visible && this.IsLoaded)
                {
                    RefreshDisplay();
                    //OnIsCheckAllChanged(false, true);
                }
            }
            catch (Exception ex)
            {
                
            }
        }

        private void _popup_Opened(object sender, EventArgs e)
        {
            //下拉框打开时刷新checkbox，因为在enable为false时搜索不到checkbox
            RefreshCheckboxState();
        }

        #region Events

        public static readonly RoutedEvent ClickEvent =
            EventManager.RegisterRoutedEvent("Click",
            RoutingStrategy.Bubble,
            typeof(RoutedEventHandler),
            typeof(CheckBoxList));
        public event RoutedEventHandler Click
        {
            add
            {
                AddHandler(ClickEvent, value);
            }
            remove
            {
                RemoveHandler(ClickEvent, value);
            }
        }

        public static readonly RoutedEvent OpenedEvent =
            EventManager.RegisterRoutedEvent("Opened",
            RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(CheckBoxList));
        public event RoutedEventHandler Opened
        {
            add
            {
                AddHandler(OpenedEvent, value);
            }
            remove
            {
                RemoveHandler(OpenedEvent, value);
            }
        }

        public static readonly RoutedEvent ClosedEvent =
            EventManager.RegisterRoutedEvent("Closed",
            RoutingStrategy.Bubble,
            typeof(RoutedEventHandler),
            typeof(CheckBoxList));
        public event RoutedEventHandler Closed
        {
            add
            {
                AddHandler(ClosedEvent, value);
            }
            remove
            {
                RemoveHandler(ClosedEvent, value);
            }
        }

        #endregion

        #region Event Handlers
        private void OnMouseDownOutsideCapturedElement(object sender, MouseButtonEventArgs e)
        {
            CloseDropDown(true);
        }

        private void CheckBoxList_Click(object sender, RoutedEventArgs e)
        {
            OnClick();
        }

        void CanExecuteChanged(object sender, EventArgs e)
        {
            CanExecuteChanged();
        }

        private void Popup_Opened(object sender, EventArgs e)
        {
            //Set the focus on the content of the ContentPresenter.
            if (_contentPresenter != null)
            {
                _contentPresenter.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
            }
            if (_textBox != null)
            {
                _textBox.Focus();
            }
            BuildUpCheckBox();
            Mouse.Capture(this, CaptureMode.SubTree);
        }

        #endregion

        #region Methods

        private bool innerChangedAll = false;
        private void RefreshCheckboxState()
        {

            foreach (var checkbox in GetCheckBoxes())
            {
                if (checkbox == null)
                    continue;
                if (DisableItems != null && DisableItems.Contains(checkbox.DataContext))
                {
                    checkbox.IsEnabled = false;
                }
                if (SelectedItems == null || SelectedItems.Count == 0)
                    continue;
                if (Contains(SelectedItems, checkbox.DataContext))
                {
                    checkbox.IsChecked = true;
                }
                else
                {
                    checkbox.IsChecked = false;
                }
            }
        }
        private bool Contains(IList list, object item)
        {
            if (item is DictType && list is IList<DictType>)
            {
                return list != null && (list as IList<DictType>).FirstOrDefault(x => x.Id == (item as DictType).Id) != null;
            }
            else
            {
                return list != null && list.Contains(item);
            }

            CheckedToIsAllCheck();
        }
        private void CanExecuteChanged()
        {
            if (Command != null)
            {
                RoutedCommand command = Command as RoutedCommand;

                // If a RoutedCommand.
                if (command != null)
                    IsEnabled = command.CanExecute(CommandParameter, CommandTarget) ? true : false;
                // If a not RoutedCommand.
                else
                    IsEnabled = Command.CanExecute(CommandParameter) ? true : false;
            }
        }

        /// <summary>
        /// Closes the drop down.
        /// </summary>
        private void CloseDropDown(bool isFocusOnButton)
        {
            if (IsOpen)
                IsOpen = false;
            ReleaseMouseCapture();

            if (isFocusOnButton)
                Button.Focus();
        }

        protected virtual void OnClick()
        {
            RaiseRoutedEvent(CheckBoxList.ClickEvent);
            RaiseCommand();
        }

        private bool InitCheckAll = false;

        private void BuildUpCheckBox()
        {
            var checkBoxes = GetCheckBoxes();
            foreach (var checkBox in checkBoxes)
            {
                checkBox.Click -= new RoutedEventHandler(CheckBox_Clicked);
                checkBox.Click += new RoutedEventHandler(CheckBox_Clicked);
                SetCheckboxBinding(checkBox);
                SetCheckBoxStatus(checkBox);
            }
            if (IsCheckAll && !InitCheckAll)
            {
                OnIsCheckAllChanged(false, true);
                InitCheckAll = true;
            }
        }

        private void CheckBox_Clicked(object sender, RoutedEventArgs e)
        {
            Refresh(sender as CheckBox);
        }

        private void SetCheckboxBinding(CheckBox checkBox)
        {
            Binding contentBinding = new Binding(SelectedTextPath);
            contentBinding.Source = checkBox.DataContext;
            contentBinding.Mode = BindingMode.OneWay;
            checkBox.SetBinding(CheckBox.ContentProperty, contentBinding);
        }

        private void SetCheckBoxStatus(CheckBox checkBox)
        {
            if (SelectedItems != null && SelectedItems.Count > 0)
                checkBox.IsChecked = this.Contains(SelectedItems, checkBox.DataContext);//SelectedItems.Contains(checkBox.DataContext);
        }

        private void Refresh(CheckBox cbo)
        {
            UpdateSelectedItems(cbo);
            RefreshDisplayText();
        }

        /// <summary>
        /// 外界对选中项赋值后刷新文本框
        /// </summary>
        public void RefreshDisplay()
        {
            if (_popup == null)
            {
                return;
            }
            _popup.IsOpen = true;
            RefreshDisplayText();
            _popup.IsOpen = false;
        }

        /// <summary>
        /// Raises routed events.
        /// </summary>
        private void RaiseRoutedEvent(RoutedEvent routedEvent)
        {
            RoutedEventArgs args = new RoutedEventArgs(routedEvent, this);
            RaiseEvent(args);
        }

        /// <summary>
        /// Raises the command's Execute event.
        /// </summary>
        private void RaiseCommand()
        {
            if (Command != null)
            {
                RoutedCommand routedCommand = Command as RoutedCommand;

                if (routedCommand == null)
                    ((ICommand)Command).Execute(CommandParameter);
                else
                    routedCommand.Execute(CommandParameter, CommandTarget);
            }
        }

        /// <summary>
        /// Unhooks a command from the Command property.
        /// </summary>
        /// <param name="oldCommand">The old command.</param>
        /// <param name="newCommand">The new command.</param>
        private void UnhookCommand(ICommand oldCommand, ICommand newCommand)
        {
            EventHandler handler = CanExecuteChanged;
            oldCommand.CanExecuteChanged -= handler;
        }

        /// <summary>
        /// Hooks up a command to the CanExecuteChnaged event handler.
        /// </summary>
        /// <param name="oldCommand">The old command.</param>
        /// <param name="newCommand">The new command.</param>
        private void HookUpCommand(ICommand oldCommand, ICommand newCommand)
        {
            EventHandler handler = new EventHandler(CanExecuteChanged);
            canExecuteChangedHandler = handler;
            if (newCommand != null)
                newCommand.CanExecuteChanged += canExecuteChangedHandler;
        }

        #endregion //Methods

        #region ICommandSource Members

        // Keeps a copy of the CanExecuteChnaged handler so it doesn't get garbage collected.
        private EventHandler canExecuteChangedHandler;

        #region Command

        public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(CheckBoxList), new PropertyMetadata((ICommand)null, OnCommandChanged));
        [TypeConverter(typeof(CommandConverter))]
        public ICommand Command
        {
            get
            {
                return (ICommand)GetValue(CommandProperty);
            }
            set
            {
                SetValue(CommandProperty, value);
            }
        }

        private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            CheckBoxList CheckBoxList = d as CheckBoxList;
            if (CheckBoxList != null)
                CheckBoxList.OnCommandChanged((ICommand)e.OldValue, (ICommand)e.NewValue);
        }

        protected virtual void OnCommandChanged(ICommand oldValue, ICommand newValue)
        {
            // If old command is not null, then we need to remove the handlers.
            if (oldValue != null)
                UnhookCommand(oldValue, newValue);

            HookUpCommand(oldValue, newValue);

            CanExecuteChanged(); //may need to call this when changing the command parameter or target.
        }

        #endregion //Command

        public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(CheckBoxList), new PropertyMetadata(null));
        public object CommandParameter
        {
            get
            {
                return GetValue(CommandParameterProperty);
            }
            set
            {
                SetValue(CommandParameterProperty, value);
            }
        }

        public static readonly DependencyProperty CommandTargetProperty = DependencyProperty.Register("CommandTarget", typeof(IInputElement), typeof(CheckBoxList), new PropertyMetadata(null));
        public IInputElement CommandTarget
        {
            get
            {
                return (IInputElement)GetValue(CommandTargetProperty);
            }
            set
            {
                SetValue(CommandTargetProperty, value);
            }
        }

        #endregion //ICommandSource Members

        #region 多选逻辑

        private void UpdateSelectedItems(CheckBox cbo)
        {
            if (_container == null)
                return;

            var selectedList = new System.Collections.ArrayList();
            if (SelectedItems != null)
            {
                //防止selecteditems collectionchanged触发多次
                if (cbo.IsChecked.HasValue && cbo.IsChecked.Value)
                {
                    SelectedItems.Add(cbo.DataContext);
                }
                else
                {

                    SelectedItems.Remove(cbo.DataContext);
                }
            }
            else
            {
                foreach (var checkbox in GetCheckBoxes())
                {
                    if (checkbox != null && checkbox.IsChecked != null && checkbox.IsChecked.Value)
                        selectedList.Add(checkbox.DataContext);
                }
                SelectedItems = selectedList;
            }
        }

        private IEnumerable<CheckBox> GetCheckBoxes()
        {
            if (_container == null)
                return new List<CheckBox>();

            return FindChildren<CheckBox>(_container);
        }

        private void RefreshDisplayText()
        {
            if (_container == null)
                return;
            var checkboxContents = new List<string>();
            foreach (var checkbox in GetCheckBoxes())
            {
                if (checkbox != null && checkbox.IsChecked != null && checkbox.IsChecked.Value
                    && checkbox.Content is String)
                {
                    if (SelectedItems != null && !SelectedItems.Contains(checkbox.DataContext))
                    {
                        continue;
                    }

                    if (checkbox.DataContext != null && !string.IsNullOrEmpty(DisplayMemberPath))
                    {
                        var context = checkbox.DataContext;
                        var value = GetPropertyValue(context, DisplayMemberPath);
                        if (value != null)
                        {
                            checkboxContents.Add(value.ToString());
                        }
                        else
                        {
                            checkboxContents.Add(string.Empty);
                        }
                    }
                    else
                    {
                        checkboxContents.Add(checkbox.Content.ToString());
                    }
                }
                else if (checkbox != null && checkbox.IsChecked != null && checkbox.IsChecked.Value
                    && checkbox.Content is DictType)
                {
                    checkboxContents.Add((checkbox.Content as DictType).Id);
                }
            }
            var displayText = string.Empty;
            if (checkboxContents.Count > 0)
            {
                displayText = string.Join(",", checkboxContents.ToArray());
            }
            DisplayText = displayText;

            CheckedToIsAllCheck();
        }

        private void CheckedToIsAllCheck()
        {
            //反馈到全选按钮中去
            if (ShowCheckAll && innerChangedAll == false)
            {
                bool isChkAll = true;
                foreach (var checkbox in GetCheckBoxes())
                {
                    if (checkbox == null)
                        continue;
                    if (DisableItems != null && DisableItems.Contains(checkbox.DataContext))
                    {
                        continue;
                    }
                    if (checkbox.IsChecked == false)
                    {
                        isChkAll = false;
                        break;
                    }
                }

                innerChangedAll = true;
                IsCheckAll = isChkAll;
                innerChangedAll = false;
            }
        }

        private ItemsControl GetCheckBoxContainer(DependencyObject obj)
        {
            var itemsControls = FindChildren<ItemsControl>(obj);
            var checkBoxContainer = itemsControls.FirstOrDefault(p => p.Name == "checkBoxContainer"); ;
            return checkBoxContainer;
        }

        private IEnumerable<T> FindChildren<T>(DependencyObject parent) where T : class
        {
            var count = VisualTreeHelper.GetChildrenCount(parent);
            if (count > 0)
            {
                for (var i = 0; i < count; i++)
                {
                    var child = VisualTreeHelper.GetChild(parent, i);
                    var t = child as T;
                    if (t != null)
                        yield return t;

                    var children = FindChildren<T>(child);
                    foreach (var item in children)
                        yield return item;
                }
            }
        }

        #endregion

        private void _popup_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.Key)
            {
                case Key.F3:
                    IsCheckAll = true;
                    e.Handled = true;
                    break;
                case Key.F4:
                    IsCheckAll = false;
                    e.Handled = true;
                    break;
                default:
                    break;
            }
        }
    }
}
